﻿using System.Data;

namespace System
{
    public static class TypeConvertExtension
    {
        public static uint ObjToUint(this object @this, uint defaultValue = 0)
        {
            if (@this is not null && @this != DBNull.Value && uint.TryParse(@this.ToString(), out uint value))
            {
                return value;
            }
            return defaultValue;
        }

        public static int ObjToInt(this object @this, int defaultValue = 0)
        {
            if (@this is not null && @this != DBNull.Value && int.TryParse(@this.ToString(), out int value))
            {
                return value;
            }
            return defaultValue;
        }

        public static short ObjToInt16(this object @this, short defaultValue = 0)
        {
            if (@this is not null && @this != DBNull.Value && short.TryParse(@this.ToString(), out short value))
            {
                return value;
            }
            return defaultValue;
        }

        public static long ObjToInt64(this object @this, long defaultValue = 0)
        {
            if (@this is not null && @this != DBNull.Value && long.TryParse(@this.ToString(), out long value))
            {
                return value;
            }
            return defaultValue;
        }

        public static double ObjToDouble(this object @this, double defaultValue = 0)
        {
            if (@this is not null && @this != DBNull.Value && double.TryParse(@this.ToString(), out double value))
            {
                return value;
            }
            return defaultValue;
        }

        public static decimal ObjToDecimal(this object @this, decimal defaultValue = 0M)
        {
            if (@this is not null && @this != DBNull.Value && decimal.TryParse(@this.ToString(), out decimal value))
            {
                return value;
            }
            return defaultValue;
        }

        public static string ObjToString(this object @this, string defaultValue = "")
        {
            if (@this is not null) return @this.ToString().Trim();
            return defaultValue;
        }

        public static DateTime ObjToDate(this object @this) => ObjToDate(@this, DateTime.MinValue);
        public static DateTime ObjToDate(this object @this, DateTime defaultValue)
        {
            if (@this is not null && @this != DBNull.Value && DateTime.TryParse(@this.ToString(), out DateTime value))
            {
                return value;
            }
            return defaultValue;
        }

        public static bool ObjToBool(this object @this, bool defaultValue = false)
        {
            if (@this is not null && @this != DBNull.Value && bool.TryParse(@this.ToString(), out bool value))
            {
                return value;
            }
            return defaultValue;
        }

        /// <summary>
        /// string 到 DataTable
        /// </summary>
        /// <param name="strTable"></param>
        /// <param name="rowSplitChars">分解行的字符串</param>
        /// <param name="columnSplitChars">分解字段的字符串</param>
        /// <param name="isFirstRowColumn">第一行是否是DataTable的列名：true=是，false=否</param>
        /// <returns></returns>
        public static DataTable StrToDataTable(this string strTable, string[] rowSplitChars, string[] columnSplitChars, bool isFirstRowColumn = true)
        {
            if (string.IsNullOrWhiteSpace(strTable)
                || rowSplitChars == null || rowSplitChars.Length <= 0
                || columnSplitChars == null || columnSplitChars.Length <= 0)
            {
                return null;
            }
            DataTable dt = new DataTable();

            string[] strRows = strTable.Split(rowSplitChars, StringSplitOptions.RemoveEmptyEntries); //解析成行的字符串数组

            if (strRows.Length <= 0)
            {
                return null;
            }

            //数据开始行(排除标题行)
            int startRow = 0;
            //第一行中间不要出现空白字符串。否则表格会错乱
            var firstRow = strRows[0].Split(columnSplitChars, StringSplitOptions.RemoveEmptyEntries);
            if (isFirstRowColumn)
            {
                #region 标题处理
                //相同列名处理
                Dictionary<string, (int, int)> columnDic = new Dictionary<string, (int, int)>();
                string columnName;

                for (int i = 0; i < firstRow.Length; i++)
                {
                    columnName = firstRow[i];
                    if (columnDic.ContainsKey(columnName))
                    {
                        var dicItem = columnDic[columnName];
                        dicItem.Item1 += 1;//相同列名的总数加1
                        columnDic[columnName] = dicItem;
                    }
                    else
                    {
                        columnDic.Add(columnName, (0, 0));
                    }
                }

                for (int i = 0; i < firstRow.Length; i++)
                {
                    columnName = firstRow[i];
                    var dicItem = columnDic[columnName];
                    if (dicItem.Item1 > 0)
                    {
                        dicItem.Item2 += 1; //当前顺序加1
                        columnDic[columnName] = dicItem;
                        columnName += dicItem.Item2.ToString();
                    }

                    dt.Columns.Add(new DataColumn(columnName));
                }
                #endregion
                startRow = 1;
            }
            else
            {
                string columnName;
                for (int i = 0; i < firstRow.Length; i++)
                {
                    columnName = "Column" + i.ToString();
                    dt.Columns.Add(new DataColumn(columnName));
                }
            }

            for (int rowIndex = startRow; rowIndex < strRows.Length; rowIndex++)       //行的字符串数组遍历
            {
                string vsRow = strRows[rowIndex]; //取行的字符串
                string[] vsColumns = vsRow.Split(columnSplitChars, StringSplitOptions.None); //解析成字段数组

                string[] columns = new string[dt.Columns.Count];
                var isAllRowEmpty = true;
                for (int i = 0; i < dt.Columns.Count; i++)
                {
                    if (vsColumns.Length <= i) continue;
                    columns[i] = vsColumns[i].Trim();
                    if (!string.IsNullOrEmpty(columns[i]))
                    {
                        isAllRowEmpty = false;
                    }
                }
                if (isAllRowEmpty == false) //排除空行
                {
                    dt.Rows.Add(columns);
                }
            }
            return dt;
        }
    }
}
